package com.springcloud.service;

import com.springcloud.hystrix.MyFallback;
import com.springcloud.hystrix.MyFallbackFactory;
import com.springcloud.model.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;
import java.util.Map;

/**
 * 自定义声明式服务消费接口
 * @FeignClient 标记当前接口是一个声明式服务消费接口,Spring会为这个接口创建动态代理对象并
 * 定义到Spring应用上下文中
 *  属性:
 *    name 用于指定以注册中心中的服务名
 *    fallback 用于指定当前声明式服务消费接口的服务熔断器类,这个类必须是当前声明式服务消费接口的子类
 *             当声明式服务消费接口中的某个方法抛出异常后则会自动调用fallback所指定的这个类中的对应方法实现服务熔断
 *    fallbackFactory 与fallback属性作用相同,但是区别在这个属性所指定的类可以获取熔断时的异常信息
 */
//@FeignClient(name = "07-feign-provider",fallback = MyFallback.class)
@FeignClient(name = "07-feign-provider",fallbackFactory = MyFallbackFactory.class)
public interface ProviderService {
    /**
     * 声明式服务消费方法,Spring会在动态代理对象中实现这个方法
     * 并根据注解@RequestMapping的规则使用对应的方式访问远程的具体服务
     * @RequestMapping的参数为需要访问的远程服务的具体请求地址
     */
    @RequestMapping("/test")
    String test();

    @RequestMapping("/getUser")
    String getUser01();
    @RequestMapping("/getUser")
    Map getUser02();
    @RequestMapping("/getUser")
    User getUser03();

    //服务提供者返回的是Json对象数组所以需要使用List或Set集合封住数据
    //没有指定返回值类型的集合的泛型因此会使用LinkedHashMap作为集合中的元素
    @RequestMapping("/getUserList")
    List getUserList01();
    //服务提供者返回的是Json对象数组所以需要使用List或Set集合封住数据
    //指定返回值类型的集合的泛型为User因此会使用User作为集合中的元素
    @RequestMapping("/getUserList")
    List<User> getUserList02();

    /**
     * {name}和{age}为地址路径的占位符需要后期动态赋值
     * @PathVariable 用于标记当前形参为请求地址路径的动态数据,
     * 如果形参名与占位符的名字相同这个注解可以不指定任何的参数
     * 如果形参名与占位符名字不相同则需要为这个注解指定参数来进行校正
     */
    @RequestMapping("/params01?name={name}&age={age}")
    User params01(@PathVariable("name") String sname,@PathVariable Integer age);

    /**
     * @RequestParam 用于标记当前形参为请求的参数数据,默认使用形参名作为请求的参数名
     * 如果服务提供者获取数据的规则名与当前形参名不同则需要指定@RequestParam注解中的属性进行校正
     */
    @RequestMapping("/params01")
    User params02(@RequestParam("name") String sname, @RequestParam Integer age);

    /**
     * 如果使用对象传递参数那么服务提供者也不需要使用对象来接收数据并且必须为这个对象标记@RequestBody
     * 因为消费者会默认将对象存入请求体中,而消费者同时最多可以有1个对象参数存入请求体
     */
    @RequestMapping("/paramsObj")
    User paramsObj( User user);
    @RequestMapping("/paramsList")
    List<User> paramsList( List<User> list);
    @RequestMapping("/paramsJson")
    User paramsJson( @RequestParam String paramsJson);
}
